export interface ValidationReason {
  category: '社会工程学' | '字典攻击';
  details: string[];
}

export interface PasswordValidationResult {
  isValid: boolean;
  message: string;
  suggestion?: string;
  reasons?: ValidationReason[];
}

// 常见弱密码列表
const WEAK_PASSWORDS = [
  // 常见数字组合
  '123456', '12345678', '123456789', '123123', '111111', '000000',
  
  // 简单字母组合
  'password', 'qwerty', 'abc123', 'admin', 'welcome', 'login', 
  'letmein', 'master', 'sunshine', 'password1', 'passw0rd',
  
  // 常见单词和短语
  'iloveyou', 'princess', 'monkey', 'football', 'baseball',
  'superman', 'batman', 'starwars', 'trustno1', 'hello123',
  
  // 键盘相邻键组合
  '1qaz2wsx', 'qazwsx', 'asdfgh', 'zxcvbn', '!@#$%^',
  ];

// 社会工程学密码特征检查
function checkSocialEngineering(password: string, username: string): boolean {
  // 当用户名为空时跳过相关检查
  if (username && username.trim() !== '') {
    const lowerUsername = username.toLowerCase();
    const lowerPassword = password.toLowerCase();
    
    // 检查是否包含完整用户名
    if (lowerPassword.includes(lowerUsername)) {
      return true;
    }
    
    // 检查用户名中任意连续4个字符
    if (lowerUsername.length >= 4) {
      for (let i = 0; i <= lowerUsername.length - 4; i++) {
        const substring = lowerUsername.substr(i, 4);
        if (lowerPassword.includes(substring)) {
          return true;
        }
      }
    }
    
    // 检查姓名+数字模式
    const nameNumberPattern = new RegExp(`^${username}\\d+$`, 'i');
    if (nameNumberPattern.test(password)) {
      return true;
    }
  }
  
  // 检查简单数字组合（无论用户名是否为空）
  const simpleNumberPattern = /^\d+$/;
  if (simpleNumberPattern.test(password)) {
    return true;
  }

  // 检查是否为手机号码（11位且符合常见号段）
  const mobilePattern = /^1(3[0-9]|4[579]|5[0-35-9]|6[2567]|7[0-35-8]|8[0-9]|9[0-9])\d{8}$/;
  if (mobilePattern.test(password)) {
    return true;
  }
  
  return false;
}

// 字典攻击特征检查
function checkDictionaryAttack(password: string): boolean {
  // 检查是否为常见弱密码
  if (WEAK_PASSWORDS.includes(password.toLowerCase())) {
    return true;
  }
  
  // 检查密码长度是否过短
  if (password.length < 8) {
    return true;
  }
  
  // 检查是否缺乏复杂性（必须包含大小写字母、数字和特殊字符）
  const hasUpper = /[A-Z]/.test(password);
  const hasLower = /[a-z]/.test(password);
  const hasNumber = /\d/.test(password);
  const hasSpecialChar = /[!@#$%^&*()_\-+=,.?":{}|<>\[\]\\\/]/.test(password);
  
  // 必须同时满足以下条件：
  // 1. 包含大小写字母
  // 2. 包含数字
  // 3. 包含特殊字符
  if (!(hasUpper && hasLower && hasNumber && hasSpecialChar)) {
    return true;
  }
  
  return false;
}

// 全局字符集定义
const lowercase = 'abcdefghijklmnopqrstuvwxyz';
const uppercase = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
const numbers = '0123456789';
const specialChars = '!@#$%^&*()_\-+=,.?":{}|<>[]\\/';

// 生成推荐密码
export function generateSuggestion(currentPassword?: string, username?: string): string {
  // 如果提供了当前密码，尝试改进它
    if (currentPassword) {
      let improved = currentPassword;
      const lowerUsername = username?.toLowerCase() || '';
      const lowerImproved = improved.toLowerCase();
      
      // 确保improved变量在函数内部始终可用
      if (!improved) {
        improved = currentPassword;
      }

    // 检查是否为简单数字组合
    if (/^\d+$/.test(currentPassword)) {
      // 检查是否为重复数字密码
      const isRepeatingDigits = /^(\d)\1+$/.test(currentPassword);
      const digits = currentPassword.split('');
      
      if (isRepeatingDigits) {
        // 替换部分重复数字为其他随机数字
        const originalDigit = digits[0];
        const digitsToReplace = Math.max(2, Math.floor(digits.length / 2));
        
        for (let i = 0; i < digitsToReplace; i++) {
          const replacePos = Math.floor(Math.random() * digits.length);
          let newDigit;
          do {
            newDigit = numbers[Math.floor(Math.random() * numbers.length)];
          } while (newDigit === originalDigit);
          digits[replacePos] = newDigit;
        }
      } else {
        // 普通数字组合，打乱所有数字顺序
        for (let i = digits.length - 1; i > 0; i--) {
          const j = Math.floor(Math.random() * (i + 1));
          [digits[i], digits[j]] = [digits[j], digits[i]];
        }
      }
      
      // 插入特殊字符和字母
      const insertPos1 = Math.floor(Math.random() * digits.length);
      const insertPos2 = Math.floor(Math.random() * digits.length);
      const specialChar = specialChars[Math.floor(Math.random() * specialChars.length)];
      const randomLetter = lowercase[Math.floor(Math.random() * lowercase.length)];
      
      improved = digits.slice(0, insertPos1).join('') + 
                specialChar + 
                digits.slice(insertPos1, insertPos2).join('') + 
                randomLetter + 
                digits.slice(insertPos2).join('');
      
      // 确保长度足够
      if (improved.length < 8) {
        const neededChars = 8 - improved.length;
        for (let i = 0; i < neededChars; i++) {
          const randomChar = specialChars[Math.floor(Math.random() * specialChars.length)];
          improved += randomChar;
        }
      }
      
      // 确保包含大写字母
      if (!/[A-Z]/.test(improved)) {
        const randomPos = Math.floor(Math.random() * improved.length);
        improved = improved.slice(0, randomPos) + 
                  uppercase[Math.floor(Math.random() * uppercase.length)] + 
                  improved.slice(randomPos);
      }
      
      return improved;
    }

    // 检查是否为手机号码
    const mobilePattern = /^1(3[0-9]|4[579]|5[0-35-9]|6[2567]|7[0-35-8]|8[0-9]|9[0-9])\d{8}$/;
    if (mobilePattern.test(currentPassword)) {
      // 对手机号码进行更彻底的变形
      const digits = currentPassword.split('');
      // 随机打乱数字顺序
      for (let i = digits.length - 1; i > 0; i--) {
        const j = Math.floor(Math.random() * (i + 1));
        [digits[i], digits[j]] = [digits[j], digits[i]];
      }
      // 插入特殊字符和字母
      const insertPos1 = Math.floor(Math.random() * digits.length);
      const insertPos2 = Math.floor(Math.random() * digits.length);
      const specialChar = specialChars[Math.floor(Math.random() * specialChars.length)];
      const randomUpper = uppercase[Math.floor(Math.random() * uppercase.length)];
      
      improved = digits.slice(0, insertPos1).join('') + 
                specialChar + 
                digits.slice(insertPos1, insertPos2).join('') + 
                randomUpper + 
                digits.slice(insertPos2).join('');
      
      // 确保长度足够
      if (improved.length < 8) {
        const neededChars = 8 - improved.length;
        for (let i = 0; i < neededChars; i++) {
          const randomChar = specialChars[Math.floor(Math.random() * specialChars.length)];
          improved += randomChar;
        }
      }
      
      return improved;
    }
    
    // 检查密码是否包含用户名和连续数字（可能是日期）
    const hasUsernameAndDate = username && username.trim() !== '' && 
                             improved.toLowerCase().includes(username.toLowerCase()) && 
                             /\d{4,}/.test(improved);

    // 增强的用户名检测逻辑
    if (username && username.trim() !== '') {
      if (!username) return generateSuggestion();
      const lowerUsername = username?.toLowerCase() || '';
      const lowerImproved = improved.toLowerCase();

      // 对包含用户名和连续数字的密码进行更彻底的处理
      if (hasUsernameAndDate) {
        // 打乱所有字符顺序
        const chars = improved.split('');
        for (let i = chars.length - 1; i > 0; i--) {
          const j = Math.floor(Math.random() * (i + 1));
          [chars[i], chars[j]] = [chars[j], chars[i]];
        }
        
        // 确保包含特殊字符和大小写字母
        const specialChar = specialChars[Math.floor(Math.random() * specialChars.length)];
        const randomUpper = uppercase[Math.floor(Math.random() * uppercase.length)];
        
        // 在随机位置插入特殊字符和大写字母
        const insertPos1 = Math.floor(Math.random() * chars.length);
        const insertPos2 = Math.floor(Math.random() * chars.length);
        
        improved = chars.slice(0, insertPos1).join('') + 
                 specialChar + 
                 chars.slice(insertPos1, insertPos2).join('') + 
                 randomUpper + 
                 chars.slice(insertPos2).join('');
        
        // 确保长度足够
        if (improved.length < 8) {
          const neededChars = 8 - improved.length;
          for (let i = 0; i < neededChars; i++) {
            const randomChar = specialChars[Math.floor(Math.random() * specialChars.length)];
            improved += randomChar;
          }
        }
        
        return improved;
      }
      
      // 1. 检测完整用户名（不区分大小写）
      // 检测所有用户名变体（包括大小写变形）
      const usernameVariants = [
        lowerUsername,
        lowerUsername.toUpperCase(),
        lowerUsername.charAt(0).toUpperCase() + lowerUsername.slice(1),
        lowerUsername.replace(/a/g, '@'),
        lowerUsername.replace(/s/g, '$'),
        lowerUsername.replace(/i/g, '1'),
        lowerUsername.replace(/o/g, '0')
      ];
      
      // 检查所有变体
      for (const variant of usernameVariants) {
        if (improved.toLowerCase().includes(variant.toLowerCase())) {
          // 生成全新随机密码（不保留原密码结构）
          return generateSuggestion();
        }
      }

        // 直接生成全新密码
        return generateSuggestion();
      }
      
      // 2. 检测用户名拆分成部分的情况（如"Wjy"拆分成"W"+"jy"）
      for (let i = 1; i < lowerUsername.length; i++) {
        const part1 = lowerUsername.substring(0, i);
        const part2 = lowerUsername.substring(i);
        if (lowerImproved.includes(part1) && lowerImproved.includes(part2)) {
          return generateSuggestion();
        }
      }
      
      // 3. 检测用户名变体（首字母大写、添加数字、特殊字符等）
      const usernameVariants = [
        lowerUsername.charAt(0).toUpperCase() + lowerUsername.slice(1), // Wjy
        `\\d*${lowerUsername}\\d*`,  // 521Wjy
        `[^a-z0-9]*${lowerUsername}[^a-z0-9]*`, // W-j-y
        `${lowerUsername}\\d{2,}`,  // Wjy521
        `\\d{2,}${lowerUsername}`,   // 521Wjy
        lowerUsername.replace(/a/g, '@'),  // Wj@
        lowerUsername.replace(/s/g, '$'),  // Wj$
        lowerUsername.replace(/i/g, '1'),  // Wj1
        lowerUsername.replace(/o/g, '0')   // Wj0
      ];
      
      for (const variant of usernameVariants) {
        const variantRegex = new RegExp(variant, 'i');
        if (variantRegex.test(improved)) {
          return generateSuggestion();
        }
      }
      
      // 4. 检测反转的用户名
      const reversedUsername = lowerUsername.split('').reverse().join('');
      if (lowerImproved.includes(reversedUsername)) {
        return generateSuggestion();
      }
      
      // 5. 检测用户名+常见后缀（如Wjy2025）
      const commonSuffixes = ['2023', '2024', '2025', '123', '456', '789', '!', '@', '#'];
      for (const suffix of commonSuffixes) {
        if (improved.endsWith(suffix) && lowerImproved.startsWith(lowerUsername)) {
          return generateSuggestion();
        }
      }
    }
    
    // 分析当前密码缺少什么类型的字符
    const hasUpper = /[A-Z]/.test(improved);
    const hasLower = /[a-z]/.test(improved);
    const hasNumber = /\d/.test(improved);
    const hasSpecial = /[^A-Za-z0-9]/.test(improved);
    
    // 保留原密码的大部分内容，只添加缺失的字符类型
    if (!hasSpecial) {
      // 在随机位置插入1-2个特殊字符
      const insertPos1 = Math.floor(Math.random() * improved.length);
      const insertPos2 = Math.floor(Math.random() * improved.length);
      const specialChar = specialChars[Math.floor(Math.random() * specialChars.length)];
      
      improved = improved.slice(0, insertPos1) + 
                specialChar + 
                improved.slice(insertPos1);
                
      // 50%概率插入第二个特殊字符
      if (Math.random() > 0.5) {
        const specialChar2 = specialChars[Math.floor(Math.random() * specialChars.length)];
        improved = improved.slice(0, insertPos2) + 
                  specialChar2 + 
                  improved.slice(insertPos2);
      }
    }
    
    // 确保其他要求也满足（但原密码Wjy202508已经满足这些）
    if (!hasUpper) {
      const randomPos = Math.floor(Math.random() * improved.length);
      improved = improved.slice(0, randomPos) + 
                improved[randomPos].toUpperCase() + 
                improved.slice(randomPos + 1);
    }
    
    if (!hasLower) {
      const randomPos = Math.floor(Math.random() * improved.length);
      improved = improved.slice(0, randomPos) + 
                improved[randomPos].toLowerCase() + 
                improved.slice(randomPos + 1);
    }
    
    if (!hasNumber) {
      const randomPos = Math.floor(Math.random() * improved.length);
      improved = improved.slice(0, randomPos) + 
                Math.floor(Math.random() * 10) + 
                improved.slice(randomPos + 1);
    }
    
    // 先处理长度不足问题
    while (improved.length < 8) {
      const charsToAdd = [
        lowercase[Math.floor(Math.random() * lowercase.length)],
        uppercase[Math.floor(Math.random() * uppercase.length)],
        numbers[Math.floor(Math.random() * numbers.length)],
        specialChars[Math.floor(Math.random() * specialChars.length)]
      ];
      const randomChar = charsToAdd[Math.floor(Math.random() * charsToAdd.length)];
      const insertPos = Math.floor(Math.random() * improved.length);
      improved = improved.slice(0, insertPos) + randomChar + improved.slice(insertPos);
    }

    // 强制确保包含所有必需字符类型
    if (!hasUpper) {
      const randomPos = Math.floor(Math.random() * improved.length);
      const randomUpper = uppercase[Math.floor(Math.random() * uppercase.length)];
      improved = improved.slice(0, randomPos) + randomUpper + improved.slice(randomPos);
    }
    
    if (!hasLower) {
      const randomPos = Math.floor(Math.random() * improved.length);
      const randomLower = lowercase[Math.floor(Math.random() * lowercase.length)];
      improved = improved.slice(0, randomPos) + randomLower + improved.slice(randomPos);
    }
    
    if (!hasNumber) {
      const randomPos = Math.floor(Math.random() * improved.length);
      const randomNumber = numbers[Math.floor(Math.random() * numbers.length)];
      improved = improved.slice(0, randomPos) + randomNumber + improved.slice(randomPos);
    }
    
    if (!hasSpecial) {
      const randomPos = Math.floor(Math.random() * improved.length);
      const randomSpecial = specialChars[Math.floor(Math.random() * specialChars.length)];
      improved = improved.slice(0, randomPos) + randomSpecial + improved.slice(randomPos);
    }
    
    // 二次验证确保所有字符类型都存在
    const finalHasUpper = /[A-Z]/.test(improved);
    const finalHasLower = /[a-z]/.test(improved);
    const finalHasNumber = /\d/.test(improved);
    const finalHasSpecial = /[^A-Za-z0-9]/.test(improved);
    
    if (!(finalHasUpper && finalHasLower && finalHasNumber && finalHasSpecial)) {
      return generateSuggestion();
    }
    
    return improved;
    
  // 如果改进后的密码符合基本要求且不包含用户名则返回
  if (improved.length >= 8 && 
      /[A-Z]/.test(improved) && 
      /[a-z]/.test(improved) && 
      /\d/.test(improved) && 
      /[^A-Za-z0-9]/.test(improved)) {
    // 严格检查是否包含用户名
    if (username?.trim()) {
      const lowerUsername = username?.toLowerCase() || '';
      const lowerImproved = improved.toLowerCase();
      
      // 检查是否包含完整用户名
      if (lowerImproved.includes(lowerUsername)) {
        return generateSuggestion();
      }
      
      // 检查用户名中任意连续3个及以上字符
      const minLength = Math.min(3, lowerUsername.length);
      for (let len = lowerUsername.length; len >= minLength; len--) {
        for (let i = 0; i <= lowerUsername.length - len; i++) {
          const substring = lowerUsername.substr(i, len);
          if (lowerImproved.includes(substring)) {
            // 当密码包含用户名片段时，直接生成全新随机密码
            return generateSuggestion();
          }
        }
      }
    }
    return improved;
  }
  }

  // 否则生成全新随机密码
  const getRandomChar = (str: string) => str[Math.floor(Math.random() * str.length)];
  const base = [
    getRandomChar(lowercase),
    getRandomChar(uppercase),
    getRandomChar(numbers),
    getRandomChar(specialChars)
  ];
  
  while (base.length < 8) {
    base.push(getRandomChar(lowercase + uppercase + numbers + specialChars));
  }
  
  for (let i = base.length - 1; i > 0; i--) {
    const j = Math.floor(Math.random() * (i + 1));
    [base[i], base[j]] = [base[j], base[i]];
  }
  
  const finalPassword = base.join('');
  
  // 检查生成的随机密码是否包含用户名相关内容
  if (username && username.trim()) {
    const lowerUsername = username.toLowerCase();
    const lowerPassword = finalPassword.toLowerCase();
    
    // 确保username参数正确传递
    if (!username) {
      return generateSuggestion();
    }
    
    // 检查是否包含完整用户名
    if (lowerPassword.includes(lowerUsername)) {
      return generateSuggestion(currentPassword, username);
    }
    
    // 检查用户名中任意连续3个字符
    const minLength = Math.min(3, lowerUsername.length);
    for (let len = lowerUsername.length; len >= minLength; len--) {
      for (let i = 0; i <= lowerUsername.length - len; i++) {
        const substring = lowerUsername.substr(i, len);
        if (lowerPassword.includes(substring)) {
          return generateSuggestion(currentPassword, username);
        }
      }
    }
  }
  
  return finalPassword;
}

export function validatePassword(password: string, username: string = ''): PasswordValidationResult {
  const reasons: ValidationReason[] = [];
  
  // 社会工程学检查
  const socialEngineeringDetails: string[] = [];
  if (checkSocialEngineering(password, username)) {
    if (username && username.trim() !== '') {
      const normalizedUsername = username?.toLowerCase() || '';
      const normalizedPassword = password.toLowerCase();
      
      if (normalizedPassword.includes(normalizedUsername)) {
        socialEngineeringDetails.push('密码包含用户名或个人信息');
      }
      
      // 检查用户名中连续4个字符
      for (let i = 0; i <= normalizedUsername.length - 4; i++) {
        const substring = normalizedUsername.substr(i, 4);
        if (normalizedPassword.includes(substring)) {
          socialEngineeringDetails.push(`密码包含用户名中连续4个字符"${username.substr(i, 4)}"`);
          break;
        }
      }
      if (/^\d+$/.test(password)) {
        socialEngineeringDetails.push('密码仅为简单数字组合');
      }
      
      // 检查是否为手机号码
      const mobilePattern = /^1(3[0-9]|4[579]|5[0-35-9]|6[2567]|7[0-35-8]|8[0-9]|9[0-9])\d{8}$/;
      if (mobilePattern.test(password)) {
        socialEngineeringDetails.push('密码为手机号码格式');
      }
      if (username && new RegExp(`^${username}\\d+$`, 'i').test(password)) {
        socialEngineeringDetails.push('密码为姓名+数字的简单组合');
      }
      
      if (socialEngineeringDetails.length > 0) {
        reasons.push({
          category: '社会工程学',
          details: socialEngineeringDetails
        });
      }
    }
  }
  
  // 字典攻击检查
  const dictionaryAttackDetails: string[] = [];
  if (checkDictionaryAttack(password)) {
    if (WEAK_PASSWORDS.includes(password.toLowerCase())) {
      dictionaryAttackDetails.push('密码为常见弱密码或短语');
    }
    if (password.length < 8) {
      dictionaryAttackDetails.push('密码长度不足8位');
    }
    
    const hasUpper = /[A-Z]/.test(password);
    const hasLower = /[a-z]/.test(password);
    const hasNumber = /\d/.test(password);
    const hasSpecialChar = /[!@#$%^&*()_\-+=,.?":{}|<>\[\]\\\/]/.test(password);
    
    if (!hasUpper || !hasLower) {
      dictionaryAttackDetails.push('密码缺乏大小写字母组合');
    }
    if (!hasNumber) {
      dictionaryAttackDetails.push('密码未包含数字');
    }
    if (!hasSpecialChar) {
      dictionaryAttackDetails.push('密码未包含特殊字符');
    }
    
    if (dictionaryAttackDetails.length > 0) {
      reasons.push({
        category: '字典攻击', 
        details: dictionaryAttackDetails
      });
    }
  }
  
  const isValid = reasons.length === 0;
  
  // 当检测到用户名相关问题时，生成全新随机密码
  const hasUsernameIssue = reasons.some(r => 
    r.category === '社会工程学' && 
    r.details.some(d => d.includes('用户名'))
  );
  
  const formattedUsername = username && username.trim() !== '' ? 
    username.replace(/([a-z])([A-Z])/g, '$1 $2').toLowerCase() : '';
    
    return {
        isValid,
        message: isValid ? '密码安全强度符合要求' : '密码存在安全隐患',
        suggestion: isValid ? undefined : (() => {
            const allReasons = reasons?.flatMap(reason => 
                reason.details.map(detail => ({
                    category: reason.category,
                    detail
                }))
            ) || [];

            const groupedReasons = allReasons.reduce((acc, {category, detail}) => {
                if (!acc[category]) acc[category] = [];
                acc[category].push(detail);
                return acc;
            }, {} as Record<string, string[]>);

            const outputParts: string[] = [];

            return outputParts.join('<br><br>') + '<br><br>建议使用: ' + generateSuggestion(password, username);
        })(),
        reasons: isValid ? undefined : reasons
    };
}
